package JET.geom;

import java.util.ArrayList;

/**
 *
 * @author 057Ry
 */
public class Circle 
{
    Vec2d center;
    double radius;
    double squareRadius;
    
    public Circle(Vec2d center, double radius)
    {
        this.center = center;
        this.radius = radius;
        this.squareRadius = radius*radius;
    }

    public Vec2d getCenter() {
        return center;
    }

    public double getRadius() {
        return radius;
    }

    public double getSquareRadius() {
        return squareRadius;
    }
    
    
    /**
     * Zwraca odleglosc miedzy punktem wskazywaneym przez vec2d a srodkiem okregu.
     * 
     * @param vec2d wektor wskazujacy punkt, dla ktorego odlegloscjest obliczana.
     * @return odleglosc miedzy punktem wskazywaneym przez vec2d a srodkiem okregu.
     */
    public double getDistanceToVec2d(Vec2d vec2d)
    {
       Vec2d distVec = new Vec2d( vec2d );
       distVec.sub( this.center );
       
       return distVec.getMagnitude();
    }
    
    /**
     * Zwraca wersor kierunku od cetrum okregu do punktu wskazywanego przez wektor vec2d.
     * 
     * @param vec2d wektor wskazujacy punkt, w kierunku ktorego konstruowany jest wersor.
     * @return wersor kierunku od cetrum okregu do punktu wskazywanego przez wektor vec2d.
     */
    public Vec2d getRadiusVersorToVec2d(Vec2d vec2d)
    {
        Vec2d rN = new Vec2d(vec2d);
        rN.sub( this.center );
        rN.normalize();
        
        return rN;
    }
    /**
     * Sprawdza czy dany punkt (reprezentowany przez wektor) lezy wewnatrz
     * okregu (lub na jego krawedzi).
     * Dla wiekszej szybkosci wykoniania pod uwage brane sa jedynie :
     * - suma kwadratow odleglosci, wzdluz poszczegolnych osi, miedzy srodkiem,
     *   okregu a sprawdzanym punktem
     * - kwadrat promienia okregu
     * 
     * @param vec2d wektor wskazujacy sprawdzany punkt
     * @return true - jezeli punkt lezy wew. okregu oraz false w przeciwnym wypadku.
     */
    public boolean isVec2dInside(Vec2d vec2d)
    {
        double a = vec2d.getX() - center.getX();
        double b = vec2d.getY() - center.getY();

        if ( a*a+b*b <= this.squareRadius )
            return true;
        else
            return false;
    }
    
    /**
     * Sprawdza czy przekazany odcinek przecina okrag.
     * Jezeli przeciecie wystepuje to punkty krzyzowania okregu z odcinkiem
     * zwracane sa poprzaz kontener ArrayList zawierajacy wektory identyfikujace
     * te punkty.
     * 
     * @param sec2d odcinek
     * @return kontener ArrayList z wektorami wskazujacymi punkty przeciecia.
     */
    public ArrayList<Vec2d> getIntercestionPoints(Sec2d sec2d)
    {
        double Vx = sec2d.getVx();
        double Vy = sec2d.getVy();
        double Psx = sec2d.getV1().getX();
        double Psy = sec2d.getV1().getY();
        double a = center.getX();
        double b = center.getY();
        
        double A = Math.pow(Vx,2) + Math.pow(Vy,2);
        double B = 2*(Psx*Vx + Psy*Vy - a*Vx - b*Vy);
        double C = Math.pow(Psx,2)+Math.pow(Psy,2)- 2*(a*Psx + b*Psy) + Math.pow(a,2)+Math.pow(b,2)+Math.pow(radius, 2);
        
        double delta = B*B - 4*A*C;
        
        ArrayList<Vec2d> list = new ArrayList<Vec2d>(2);
        
        if ( delta == 0 ) // prosta jest styczny do okregu
        {
            double t = -1*B/(2*A);
            if ( t>=0 && t<=1 ) // jezeli punkt styku nalezy do odcinka
            {
                Vec2d tmp = new Vec2d(Vx*t, Vy*t);
                Vec2d result = new Vec2d( sec2d.getV1() );
                result.add(tmp);
                list.add(result);
            }
        }
        else if ( delta > 0 ) // prosta przecina okrag w 2 miejscach
        {
            double t1 = ( -1*B+Math.sqrt(delta) )/( 2*A );
            double t2 = ( -1*B-Math.sqrt(delta) )/( 2*A );
            Vec2d result1=null, result2=null;
            int resNum=0;
            if ( t1>=0 && t1<=1 ) // jezeli 1 punkt przeciecia nalezy do odcinka
            {
                Vec2d tmp = new Vec2d(Vx*t1, Vy*t1);
                
                result1 = new Vec2d( sec2d.getV1() );
                result1.add(tmp);
                list.add(result1);
            }
            if ( t2>=0 && t2<=1 ) // jezeli 2 punkt przeciecia nalezy do odcinka
            {
                Vec2d tmp = new Vec2d(Vx*t2, Vy*t2);
                
                result2 = new Vec2d( sec2d.getV1() );
                result1.add(tmp);
                list.add(result2);
            }
        }
        else if ( delta < 0 ) // prosta nie ma punktow wspolnych z okregiem
        {
        }
        return list;
    }
}
